﻿using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using NCMIS.ObjectModel;
using System.ServiceModel.Web;
using NCMIS.ObjectModel.Rest;
using System.ServiceModel.Syndication;
using NCMIS.ServiceModel.Syndication;
using NCMIS.Provider;

namespace NCMIS.ServiceModel.Ra
{
    /// <summary>
    /// Provides the Multi-Filing Services for the REST/Atom binding. The multi-filing services allows the filing/un-filing of objects
    /// into/from folders. The multi-filing services are supported only if the repository supports the multifiling or unfiling optional
    /// capabilities.
    /// </summary>
    public partial class Service : IService
    {
        /// <summary>
        /// Adds an existing fileable non-folder object to a folder.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <param name="objectId">The id of the object to file.</param>
        /// <param name="folderId">The id of the target folder, in which the filable object will be filed.</param>
        /// <param name="allVersions">Add all versions of the object to the folder if the repository supports version-specific filing.</param>
        [WebInvoke(Method = "PUT", UriTemplate = "/{repositoryId}/folderchildren/", BodyStyle = WebMessageBodyStyle.Wrapped)]
        public void AddObjectToFolder(string repositoryId, string objectId, string folderId, bool allVersions)
        {
            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;
            ctx.ContentType = CmisContentType.Feed;

            // Repository ID and Object ID must be specified
            if (String.IsNullOrEmpty(repositoryId) || String.IsNullOrEmpty(objectId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and objectId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return;
            }

            // Add the object to the specified folder
            MultiFilingProviderManager.Provider.AddObjectToFolder(repositoryId, objectId, folderId, allVersions);
        }

        
        /// <summary>
        /// Gets all the unfiled documents int the repository.
        /// NOTE: The CMIS specification mentions this method however is not clear about its signature or which service it is a part of.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <returns>CmisObjectList, containing all the unfiled documents in the repository, formatted as Atom 1.0 Feed.</returns>
        [WebGet(UriTemplate = "/{repositoryId}/unfiled")]
        public Atom10FeedFormatter GetUnfiled(string repositoryId)
        {
            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;
            ctx.ContentType = CmisContentType.Feed;

            // Repository ID must be specified
            if (String.IsNullOrEmpty(repositoryId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and folderId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return null;
            }

            // Store the unfiled objects in a cmisObjectList
            CmisObjectList cmisObjectList = MultiFilingProviderManager.Provider.GetUnfiled(repositoryId);

            // Create a feed and add the cmisObjectList contents to it
            CmisSyndicationFeed feed = new CmisSyndicationFeed()
            {
                BaseUri = _baseUri,
                Id = "urn:uuid:unfiled-documents",
                RepositoryId = repositoryId,
                SelfLinkUri = new Uri(_baseUri, String.Format("{0}/unfiled", repositoryId)),
                ServiceLinkUri = new Uri(_baseUri, String.Format("{0}/servicedoc", repositoryId)),
                Title = new TextSyndicationContent("Unfiled Documents"),
            };
            feed.AddEntries(cmisObjectList);
            feed.AddNumItems();

            // Format the feed as an Atom feed
            return new Atom10FeedFormatter(feed);
        }
        
        
        /// <summary>
        /// Removes an existing fileable non-folder object from a folder.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="folderId">The id of the folder.</param>
        [WebInvoke(Method = "POST", UriTemplate = "/{repositoryId}/unfiled/{objectId}")]
        public void RemoveObjectFromFolder(string repositoryId, string objectId)
        {
            string folderId = RequestParameter.FolderId;

            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;
            ctx.ContentType = CmisContentType.Feed;

            // Repository ID and Object ID must be specified
            if (String.IsNullOrEmpty(repositoryId) || String.IsNullOrEmpty(objectId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and objectId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return;
            }

            // Remove the object to the specified folder
            MultiFilingProviderManager.Provider.RemoveObjectFromFolder(repositoryId, objectId, folderId);
        }
    }
}
